
from bs4 import BeautifulSoup   # 网页解析获取数据
import re   # 正则表达式
import urllib.request, urllib.error   # 指定 url
import xlwt   # excel
import sqlite3

def main():

    baseUrl = "https://movie.douban.com/top250?start="

    dataList = getData(baseUrl)

    savePath = "豆瓣电影Top250.xls"

    saveData(dataList, savePath)

    # askURL(baseUrl)

# 影片链接
findLink = re.compile(r'<a href="(.*?)">') # 创建正则表达式对象, 表示规则(字符串模式)  r 是忽视所有的特殊符号 .代表一个字符 *代表有多个字符 ?代表0次或1次 ()代表一个组
# 影片图片
findImgSrc = re.compile(r'<img.*src="(.*?)"', re.S) # 让换行符包含在字符中
# 影片名称
findTitle = re.compile(r'<span class="title">(.*)</span>')
# 影片评分
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
# 评价人数
findJudge = re.compile(r'<span>(\d*)人评价</span>')
# 概况
findInq = re.compile(r'<span class="inq">(.*)</span>')
# 影片相关内容
findBd = re.compile(r'<p class="">(.*?)</p>', re.S)

# 爬取网页
def getData(baseUrl):
    dataList = []

    for i in range(0, 10):
        url = baseUrl + str(i*25)
        html = askURL(url)

        # 逐一解析
        soup = BeautifulSoup(html, "html.parser")
        for item in soup.find_all('div', class_="item"):   # 查找符合要求的字符串形成列表
            # print(item)
            data = []   # 保存一部电影的所有信息

            item = str(item)  # 转换成字符串

            link = re.findall(findLink, item)[0]   # re 库用来通过正则表达式查找指定的字符串
            data.append(link)

            imgSrc = re.findall(findImgSrc, item)[0]
            data.append(imgSrc)

            title = re.findall(findTitle, item) # 影片名称可能只有一个中文名, 没有外国名
            if len(title) == 2:
                zhTitle = title[0]
                data.append(zhTitle)
                usTitle = title[1].replace("/", "") # 去掉无关的符号
                data.append(usTitle)
            else:
                data.append(title[0])
                data.append(" ")  # 占位外国名留空 因为要存在 excel 中

            rating = re.findall(findRating, item)[0]
            data.append(rating)

            judgeNum = re.findall(findJudge, item)[0]
            data.append(judgeNum)

            inq = re.findall(findInq, item)
            if len(inq) != 0:
                inq = inq[0].replace("。", "")
                data.append(inq)  # 去掉句号
            else:
                data.append(" ")  # 留空

            bd = re.findall(findBd, item)[0]
            bd = re.sub('<br(\s+)?/>(\s+)?', " ", bd)            # 替换 <br/>
            bd = re.sub("/", " ", bd)                      # 替换 /
            data.append(bd.strip())                        # 去掉前后的空格 strip()

            dataList.append(data)                          # 处理好的一部电影

    # print(dataList)
    return dataList

# 得到指定一个URL的网页内容
def askURL(url):
    head = {   # 伪装成是浏览器请求
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36"
    }
    request = urllib.request.Request(url, headers=head)
    html = ""
    try:
        response = urllib.request.urlopen(request)
        html = response.read().decode("utf-8")
    except urllib.error.URLError as e:
        if hasattr(e, "code"):
            print(e.code)
        if hasattr(e, "reason"):
            print(e.reason)

    return html

# 保存数据
def saveData(dataList, savePath):
    print("save....")
    book = xlwt.Workbook(encoding="utf-8", style_compression=0)
    sheet = book.add_sheet('豆瓣电影Top250', cell_overwrite_ok=True)
    col = ("电影链接", "图片链接", "影片中文名", "影片外国名", "评分", "评价数", "概况", "相关信息")
    for i in range(0, 8):
        sheet.write(0, i, col[i])
    for i in range(0, 250):
        print("第%d条" %(i+1))
        data = dataList[i]
        for j in range(0, 8):
            sheet.write(i+1, j, data[j])
    book.save(savePath)


if __name__ == "__main__":  # 当程序执行时
    # 调用函数
    main()
    print("爬取成功!")


